Go Language Basics Quick Reference Guide
Glaringly Obvious Things (If You're New to Go)
- No
try/catch
→ Useerror
returns instead. - Functions are first-class citizens → Functions can be assigned to variables and passed around.
- Runes → Go uses
rune
for Unicode characters (alias forint32
). - No pointer arithmetic → Unlike C, you can't perform arithmetic on pointers.
- Garbage collected → No manual memory management like
malloc/free
. - Everything starts with a
main()
function → Similar to C. - No
while
loop → Usefor
loops instead. - Interfaces are implemented implicitly → No
implements
keyword. - Link to Go Proverbs → Core philosophy and best practices.
Concepts And Syntax
Variables and Constants
var x int = 10
var y = 20 // Type inferred
z := 30 // Short declaration
const Pi = 3.14
Functions
func add(a int, b int) int {
return a + b
}
func main() {
result := add(2, 3)
fmt.Println(result)
}
Control Flow
If-Else
if x > 10 {
fmt.Println("x is greater than 10")
} else if x == 10 {
fmt.Println("x is 10")
} else {
fmt.Println("x is less than 10")
}
Switch
switch x {
case 1:
fmt.Println("One")
case 2, 3:
fmt.Println("Two or Three")
default:
fmt.Println("Other")
}
Loops
For Loop
for i := 0; i < 5; i++ {
fmt.Println(i)
}
While-Style Loop
x := 0
for x < 5 {
fmt.Println(x)
x++
}
Infinite Loop
for {
fmt.Println("Looping forever")
}
Arrays and Slices
var arr [3]int = [3]int{1, 2, 3} // Fixed-size array
slice := []int{4, 5, 6} // Dynamic slice
slice = append(slice, 7) // Append to slice
Maps (Hashmaps)
m := map[string]int{"foo": 42, "bar": 99}
m["baz"] = 100
fmt.Println(m["foo"]) // 42
Structs
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 25}
fmt.Println(p.Name)
Pointers
x := 10
ptr := &x // Pointer to x
fmt.Println(*ptr) // Dereference pointer
Goroutines (Concurrency)
func sayHello() {
fmt.Println("Hello")
}
go sayHello() // Run in a goroutine
Channels
ch := make(chan int)
go func() { ch <- 42 }()
x := <-ch // Receive from channel
fmt.Println(x)
Error Handling
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
Defer, Panic, and Recover
func main() {
defer fmt.Println("Executed at the end")
fmt.Println("Start")
}
Interfaces
type Speaker interface {
Speak() string
}
type Dog struct {}
func (d Dog) Speak() string {
return "Woof!"
}
var s Speaker = Dog{}
fmt.Println(s.Speak())
Generics (Go 1.18+)
type Number interface {
int | float64
}
func add[T Number](a, b T) T {
return a + b
}
Key Go Concepts to Understand
1. Value vs Reference Types
- Only pointers, interfaces, slices, maps, channels, and function types can be
nil
. - Strings are value types, so they always have a default value (
""
, an empty string).- This is why
sql.NullString
exists, as it allows distinguishing between an empty string andnil
.
- This is why
2. String Concatenation Performance
- Using
+=
for string concatenation creates new allocations each time. - Using
strings.Builder
avoids extra allocations, making it more efficient for large string operations.
3. Go Profiler (pprof)
- Use
go tool pprof
to analyze performance bottlenecks. - Example:
go test -bench . -cpuprofile=cpu.out
go tool pprof cpu.out
4. Garbage Collection and Escape Analysis
- The Go runtime has garbage collection that runs automatically.
- Use
go build -gcflags="-m"
to see escape analysis and check if variables are allocated on the heap or stack.
5. Zero Values Instead of Null
- Go does not use
null
(like JavaScript or Java). Instead, types have zero values:int
→0
string
→""
bool
→false
slice/map
→nil
6. Struct Methods and Pointer Receivers
- Methods on structs can have pointer receivers (
*T
) or value receivers (T
). - Use a pointer receiver if the method modifies the struct.
type Counter struct {
Value int
}
func (c *Counter) Increment() {
c.Value++
}
7. Interface Satisfaction Is Implicit
- There is no
implements
keyword in Go. - A type satisfies an interface if it has all required methods.
8. Avoiding Race Conditions
- Use
sync.Mutex
orsync.RWMutex
for safe concurrent access. - Example:
var mu sync.Mutex
count := 0
func increment() {
mu.Lock()
defer mu.Unlock()
count++
}
9. Use context.Context
for Cancellations
- Many Go APIs accept
context.Context
for timeouts and cancellations. - Example:
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()